package com.hepai.online.utils;

import java.security.Key;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import javax.crypto.spec.DESedeKeySpec;
import javax.crypto.spec.IvParameterSpec;

/**
 * Creat:Yx
 * Date:2018/7/10 15:07
 * Description:3DES加密工具类
 * IV:与后端定义的向量，KEY与后端定义的加密KEY
 * 3DES：CBC加密，ECB加密
 * 小知识：float/double类型转成json会丢失精度！
 */
public class My3DESUtil {

    private final static String IV = "01234567";
    private final static String ENCODING = "UTF-8";
    public final static String KEY = "szshqtx2014hpzx090415#@1";


    /**
     * DES CBC加密
     * PS:不容易主动攻击, 安全性好于ECB,适合传输长度长的报文,是SSL、IPSec的标准; 不利于并行计算；误差传递；需要初始化向量IV
     * @param src 数据源
     * @param key 密钥，长度必须是8的倍数
     * @return 返回加密后的数据
     * @throws Exception
     */
    public static String encryptDES_CBC(final String src, final String key) throws Exception {

        // --生成key,同时制定是des还是DESede,两者的key长度要求不同
        // (DESedeKeySpec,DESKeySpec  两者加密的长度是不一样的)DESKeySpec（这貌似用在ECB模式下）
        final DESedeKeySpec desKeySpec = new DESedeKeySpec(key.getBytes());

        final SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DESede");

        //Secret key 是对称加密算法；key 是非对称加密
        final Key secretKey = keyFactory.generateSecret(desKeySpec);

        // --加密向量
        final IvParameterSpec iv = new IvParameterSpec(IV.getBytes());

        // --通过Chipher执行加密得到的是一个byte的数组,Cipher.getInstance("DESede")就是采用CBC模式,cipher.init(Cipher.ENCRYPT_MODE,
        // secretKey)就可以了.
        final Cipher cipher = Cipher.getInstance("DESede/CBC/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, secretKey, iv);
        //加密
        final byte[] b = cipher.doFinal(src.getBytes("UTF-8"));
        // --将byte数组转成base64编码格式
        return Base64.encode(b);
    }

    /**
     * DES CBC解密
     *
     * @param src 数据源
     * @param key 密钥，长度必须是8的倍数
     * @return 返回解密后的原始数据
     * @throws Exception
     */
    public static String decryptDES_CBC(final String src, final String key) throws Exception {
        // --解密的key
        final DESedeKeySpec desKeySpec = new DESedeKeySpec(key.getBytes("UTF-8"));
        final SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DESede");
        //Secret key 是对称加密算法；key 是非对称加密
        final Key secretKey = keyFactory.generateSecret(desKeySpec);

        // --向量
        final IvParameterSpec iv = new IvParameterSpec(IV.getBytes("UTF-8"));

        // --Chipher对象解密Cipher.getInstance("DESede")就是采用CBC模式,cipher.init(Cipher.DECRYPT_MODE,
        // secretKey)就可以了.
        final Cipher cipher = Cipher.getInstance("DESede/CBC/PKCS5Padding");
        cipher.init(Cipher.DECRYPT_MODE, secretKey, iv);

        // --通过base64,将字符串转成byte数组
        final byte[] bytesrc = Base64.decode(src);
        //解密
        final byte[] retByte = cipher.doFinal(bytesrc);

        return new String(retByte, ENCODING);

    }

    /**
     * 3DES ECB加密
     * 无需向量
     * PS: 简单；4102 有利于并行计算； 误差不会被传送；不能隐藏明文的模式;可能对明文进行主动攻击；
     * @param src
     * @param key 必须是长度大于等于 3*8 = 24 位哈
     * @return 返回加密后的数据
     * @throws Exception
     */
    public static String encryptThreeDES_ECB(final String src, final String key) throws Exception {
        final DESKeySpec dks = new DESKeySpec(key.getBytes("UTF-8"));
        final SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
        //对称加密
        final SecretKey securekey = keyFactory.generateSecret(dks);

        final Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, securekey);
        final byte[] b = cipher.doFinal(src.getBytes());
        return Base64.encode(b).replaceAll("\r", "").replaceAll("\n", "");

    }

    /**
     * 3DES ECB解密
     *
     * @param src
     * @param key 必须是长度大于等于 3*8 = 24 位哈
     * @return 返回解密后的数据
     * @throws Exception
     */
    public static String decryptThreeDES_ECB(final String src, final String key) throws Exception {
        // --解密的key
        final DESKeySpec dks = new DESKeySpec(key.getBytes("UTF-8"));
        final SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
        //对称加密
        final SecretKey securekey = keyFactory.generateSecret(dks);

        // --Chipher对象解密
        final Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
        cipher.init(Cipher.DECRYPT_MODE, securekey);
        // --通过base64,将字符串转成byte数组
        final byte[] bytesrc = Base64.decode(src);
        //解密
        final byte[] retByte = cipher.doFinal(bytesrc);

        return new String(retByte, ENCODING);
    }


//    public static String decode(String encryptText,String secretKey) throws Exception {
//        Key deskey = null;
//        DESedeKeySpec spec = new DESedeKeySpec(secretKey.getBytes());
//        SecretKeyFactory keyfactory = SecretKeyFactory.getInstance("desede");
//        deskey = keyfactory.generateSecret(spec);
//        Cipher cipher = Cipher.getInstance("desede/CBC/PKCS5Padding");
//        IvParameterSpec ips = new IvParameterSpec(iv.getBytes());
//        cipher.init(Cipher.DECRYPT_MODE, deskey, ips);
//
//        byte[] decryptData = cipher.doFinal(Base64.decode(encryptText));
//
//        return new String(decryptData, encoding);
}
